package org.ala.tiktools.rpc.kcp.netty.tools;

import static io.netty.util.internal.ObjectUtil.checkNotNull;

import java.util.AbstractList;
import java.util.RandomAccess;

import io.netty.util.Recycler;

/**
 * 线程间共享的List池，节省gc
 *
 * @author ala
 * @date 2025-04-15 13:06
 */
@SuppressWarnings("rawtypes")
public class CodecOutputList<T> extends AbstractList<T> implements RandomAccess {

	
	private final static Recycler<CodecOutputList> RECYCLER = new Recycler<CodecOutputList>() {
        @SuppressWarnings("unchecked")
		@Override
        protected CodecOutputList newObject(Handle<CodecOutputList> handle) {
            return new CodecOutputList(handle);
        }
    };
    private Recycler.Handle<CodecOutputList> handle;
    private CodecOutputList(Recycler.Handle<CodecOutputList> handle) {
        this.handle = handle;
    }
    /**
     *  线程间共享的对象池
     *  <p> 每个线程会持有对象栈，栈空时才取线程间共享队列
     */
    @SuppressWarnings("unchecked")
	public static <T> CodecOutputList<T> newInstance() { return RECYCLER.get(); }


    protected int size;
    protected Object[] array = new Object[8];
    boolean insertSinceRecycled = false;


    @SuppressWarnings("unchecked")
	@Override
    public T get(int index) {
        if (index >= size) { throw new RuntimeException(String.format("数组下标越界 index:%d size:%d", index, size)); }
        return (T) array[index];
    }
    @SuppressWarnings("unchecked")
	public T getUnSafe(int index) {
        return (T) array[index];
    }

    @Override
    public boolean add(T t) {
        int nsize = size + 1;
        if (nsize == array.length) {
            expandArray();
        }
        array[size] = t;
        size = nsize;
        return true;
    }

    @Override
    public void add(int index, T element) {
        checkNotNull(element, "element");
        if (index >= size) { throw new RuntimeException(String.format("数组下标越界 index:%d size:%d", index, size)); }
        if (size == array.length) { expandArray(); }
        if (index != size - 1) {
            System.arraycopy(array, index, array, index + 1, size - index);
        }
        insert(index, element);
        ++size;
    }

    @SuppressWarnings("unchecked")
	@Override
    public T set(int index, T element) {
        checkNotNull(element, "element");
        if (index >= size) { throw new RuntimeException(String.format("数组下标越界 index:%d size:%d", index, size)); }
        Object old = array[index];
        insert(index, element);
        return (T) old;
    }

    @SuppressWarnings("unchecked")
	@Override
    public T remove(int index) {
        if (index >= size) { throw new RuntimeException(String.format("数组下标越界 index:%d size:%d", index, size)); }
        Object old = array[index];
        int len = size - index - 1;
        if (len > 0) {
            System.arraycopy(array, index + 1, array, index, len);
        }
        array[--size] = null;
        return (T) old;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        size = 0;
    }

    /**
     * 归还
     */
    public void recycle() {
        //  清空每个消息
        for (int i = 0; i < array.length; i++) {
            array[i] = null;
        }
        clear();
        insertSinceRecycled = false;
        handle.recycle(this);
    }


    private void insert(int index, Object element) {
        array[index] = element;
        insertSinceRecycled = true;
    }

    /**
     * array扩容
     */
    private void expandArray() {
        int newLen = array.length;
        newLen = newLen << 1;
        if (newLen < 0) { throw new OutOfMemoryError(String.format("数组无法扩容，长度达到最大 len:%d", newLen)); }
        Object[] newArray = new Object[newLen];
        System.arraycopy(array, 0, newArray, 0, array.length);
        array = newArray;
    }

    public boolean isInsertSinceRecycled() {
        return insertSinceRecycled;
    }

    public void setInsertSinceRecycled(boolean insertSinceRecycled) {
        this.insertSinceRecycled = insertSinceRecycled;
    }
}
